/*
 * 文件名： AlipayScanCmbcServerRes.java
 * 
 * 工程名称: bis-web
 *
 * Gopay
 *
 * 创建日期： 2017年1月13日
 *
 * Copyright(C) 2017, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.web.controller.scan;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.PrivateKey;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.w3c.dom.Document;

import com.gopay.bis.domain.order.OrderInfo;
import com.gopay.bis.service.bank.BankIntrChannConfService;
import com.gopay.bis.web.controller.util.CryptoUtil;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.alipay.cmbc.AlipayHead;
import com.gopay.common.domain.bank.alipay.cmbc.AlipayNotifyBody;
import com.gopay.common.domain.bank.alipay.cmbc.AlipayTransMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanPayServerNotifyMsg;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;

/**
 * 支付宝民生渠道扫码异步服务端通知
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2017年1月13日
 */
@Controller
@Scope("prototype")
public class AlipayScanCmbcServerRes extends ScanPayBankResBase {

	public static final String AES_ENCRYPT = "AES/ECB/PKCS5Padding";
	public static final String RSA_ENCRYPT = "RSA/ECB/PKCS1Padding";

	@Resource(name = "bankIntrChannConfService")
	private BankIntrChannConfService bankIntrChannConfService;

	/**
	 * 定义日志对象
	 */
	private static Log logger = LogFactory.getLog(AlipayScanCmbcServerRes.class);

	@RequestMapping(value = "/alipayScanCmbcPayServerRes")
	protected void execute(HttpServletRequest request, HttpServletResponse response) {
		logger.error("---------------AlipayScanCmbcServerRes  bankback ---------------");
		super.execute(request, response);
	}

	@Override
	protected BaseMessage buildMessage(HttpServletRequest request) {
		ScanPayServerNotifyMsg message = (ScanPayServerNotifyMsg) toBean(request);
		message.setBank(BankConstants.BANK_LOGO_ALIPAY);
		message.setBankBusProd(BisBankBusinessProd._16);
		message.setFront(false);
		return message;
	}

	@Override
	protected OrderInfo buildOrderInfo(HttpServletRequest request, Result result) {
		ScanPayServerNotifyMsg message = (ScanPayServerNotifyMsg) result.getModel("res");
		OrderInfo orderInfo = new OrderInfo();
		if (message != null) {
			if ("0".equals(message.getPay_result())) {
				orderInfo.setOrderId(message.getOrderId());
				orderInfo.setAmt(message.getAmount().toString());
				orderInfo.setNotifyNum("1");
				orderInfo.setPayStatus("00");
				orderInfo.setRetCode("00");
				orderInfo.setRetMsg("");
				orderInfo.setIsNotify(true);
				orderInfo.setBankName(BankConstants.BANK_LOGO_ALIPAY);
			} else {
				orderInfo.setOrderId(message.getOrderId());
				orderInfo.setAmt(message.getAmount().toString());
				orderInfo.setNotifyNum("1");
				orderInfo.setPayStatus("01");
				orderInfo.setRetCode("01");
				orderInfo.setRetMsg("");
				orderInfo.setIsNotify(true);
				orderInfo.setBankName(BankConstants.BANK_LOGO_ALIPAY);
			}
		}

		return orderInfo;
	}

	@Override
	protected boolean checkParameters(HttpServletRequest request) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	protected boolean notifyBank(HttpServletResponse response, OrderInfo orderInfo) {
		try {
			response.setContentType("text/html;charset=GBK");
			// 通知民生银行成功接收银行通知
			String notifyMsg = "000000";
			logger.info("notifyBank " + orderInfo.getBankName() + " send content: \n[" + notifyMsg + "]");
			response.setContentLength(notifyMsg.getBytes().length);
			response.getOutputStream().write(notifyMsg.getBytes());
			response.getOutputStream().close();

		} catch (IOException e) {
			logger.info("notifyBank error!" + e.getMessage());
		}
		return true;
	}

	public BaseMessage toBean(HttpServletRequest request) {
		/**
		 * 获取银行接口通道配置信息
		 */
		BaseBisBankExtConfig bankConfig = bankIntrChannConfService.findBaseBisBankExtConfigByBankChannel(
				BisBankBusinessProd._16, BisBankInterfaceChannel._17, BankConstants.BANK_LOGO_ALIPAY);
		String charset = "utf-8";
		ScanPayServerNotifyMsg result = new ScanPayServerNotifyMsg();
		try {
			request.setCharacterEncoding(charset);
			String resEncryptData = request.getParameter("encryptData");
			String resEncryptKey = request.getParameter("encryptKey");
			String signData = request.getParameter("signData");
			String reqMsgId = request.getParameter("reqMsgId");
			logger.info("----alipay cmbc notify reqMsgId : " + reqMsgId);
			logger.info("----alipay cmbc notify encryptData : " + resEncryptData + " ; encryptKey:" + resEncryptKey
					+ " ; signData:" + signData);
			PrivateKey hzfPriKey = null;
			byte[] merchantXmlDataBytes = null;
			hzfPriKey = CryptoUtil.getRSAPrivateKeyByFileSuffix(bankConfig.getIntrMerPravkeyPath(), "pem", null, "RSA");
			byte[] decodeBase64KeyBytes = Base64.decodeBase64(resEncryptKey.getBytes(charset));
			// 解密encryptKey得到merchantAESKey
			byte[] merchantAESKeyBytes = CryptoUtil.RSADecrypt(decodeBase64KeyBytes, hzfPriKey, 2048, 11, RSA_ENCRYPT);
			// 使用base64解码民生请求报文
			byte[] decodeBase64DataBytes = Base64.decodeBase64(resEncryptData.getBytes(charset));
			// 用解密得到的merchantAESKey解密encryptData
			merchantXmlDataBytes = CryptoUtil.AESDecrypt(decodeBase64DataBytes, merchantAESKeyBytes, "AES", AES_ENCRYPT,
					null);
			String plainText = new String(merchantXmlDataBytes, charset);
			logger.info("------alipay cmbc notify plainText :" + plainText);

//			AlipayTransMsg<AlipayNotifyBody> res = XmlBeanUtil.toBean(plainText, AlipayTransMsg.class,
//					AlipayNotifyBody.class);
			AlipayTransMsg<AlipayNotifyBody> res =generateResQueryMessage(plainText);
			AlipayNotifyBody body = res.getBody();
			if (StringUtils.equalsIgnoreCase("S", res.getHead().getRespType())) {
				result.setPay_result("0");
			}
			result.setPlainMessage(plainText);
			result.setSignMessage(signData);
			result.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
			result.setAmount(body.getTotalAmount());
			result.setBankOrderId(body.getReqMsgId());
		} catch (Exception e) {
			logger.error("解密民生银行通知信息异常"+e);
		}
		return result;
	}
	public AlipayTransMsg<AlipayNotifyBody> generateResQueryMessage(String plainText) throws Exception {
		AlipayHead head = new AlipayHead();
		AlipayNotifyBody body = new AlipayNotifyBody();
		AlipayTransMsg<AlipayNotifyBody> resMessage = new AlipayTransMsg<AlipayNotifyBody>();
		// 解析文件，生成document对象
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		InputStream inputStream = new ByteArrayInputStream(plainText.getBytes());
		Document document = builder.parse(inputStream);
		// 生成XPath对象
		XPath xpath = XPathFactory.newInstance().newXPath();
		generateResHeadMessage(document, xpath, head);
		String buyerId = (String) xpath.evaluate("/message/body/buyerId/text()", document, XPathConstants.STRING);
		String buyerAccount = (String) xpath.evaluate("/message/body/buyerAccount/text()", document, XPathConstants.STRING);
		String totalAmount = (String) xpath.evaluate("/message/body/totalAmount/text()", document, XPathConstants.STRING);
		String buyerPayAmount = (String) xpath.evaluate("/message/body/buyerPayAmount/text()", document, XPathConstants.STRING);
		String pointAmount = (String) xpath.evaluate("/message/body/pointAmount/text()", document, XPathConstants.STRING);
		//String payTime = (String) xpath.evaluate("/message/body/payTime/text()", document, XPathConstants.STRING);
		//String settleDate = (String) xpath.evaluate("/message/body/settleDate/text()", document, XPathConstants.STRING);
		String isClearOrCancel = (String) xpath.evaluate("/message/body/isClearOrCancel/text()", document, XPathConstants.STRING);
		//String channelNo = (String) xpath.evaluate("/message/body/channelNo/text()", document, XPathConstants.STRING);
		String reqMsgId = (String) xpath.evaluate("/message/body/reqMsgId/text()", document, XPathConstants.STRING);		
		//String payType = (String) xpath.evaluate("/message/body/payType/text()", document, XPathConstants.STRING);
		
		String extend1 = (String) xpath.evaluate("/message/body/extend1/text()", document, XPathConstants.STRING);
		String extend2 = (String) xpath.evaluate("/message/body/extend2/text()", document, XPathConstants.STRING);
		String extend3 = (String) xpath.evaluate("/message/body/extend3/text()", document, XPathConstants.STRING);
		
		body.setBuyerId(buyerId);
		body.setBuyerAccount(buyerAccount);
		body.setTotalAmount(StringUtils.isNotBlank(totalAmount)?new BigDecimal(totalAmount):new BigDecimal(0));
		body.setBuyerPayAmount(StringUtils.isNotBlank(buyerPayAmount)?new BigDecimal(buyerPayAmount):new BigDecimal(0));
		body.setPointAmount(StringUtils.isNotBlank(pointAmount)?new BigDecimal(pointAmount):new BigDecimal(0));
		body.setIsClearOrCancel(isClearOrCancel);
		body.setReqMsgId(reqMsgId);
		body.setExtend1(extend1);
		body.setExtend2(extend2);
		body.setExtend3(extend3);
		resMessage.setHead(head);
		resMessage.setBody(body);
		return resMessage;
	}
	public AlipayHead generateResHeadMessage(Document document, XPath xpath, AlipayHead head) throws Exception {
		// 获取节点值
		String version = (String) xpath.evaluate("/message/head/version/text()", document, XPathConstants.STRING);
		String msgType = (String) xpath.evaluate("/message/head/msgType/text()", document, XPathConstants.STRING);
		String smzfMsgId = (String) xpath.evaluate("/message/head/smzfMsgId/text()", document, XPathConstants.STRING);
		String reqDate = (String) xpath.evaluate("/message/head/reqDate/text()", document, XPathConstants.STRING);
		String respDate = (String) xpath.evaluate("/message/head/respDate/text()", document, XPathConstants.STRING);
		String respType = (String) xpath.evaluate("/message/head/respType/text()", document, XPathConstants.STRING);
		String respCode = (String) xpath.evaluate("/message/head/respCode/text()", document, XPathConstants.STRING);
		String respMsg = (String) xpath.evaluate("/message/head/respMsg/text()", document, XPathConstants.STRING);
		head.setVersion(version);
		head.setMsgType(msgType);
		head.setReqDate(reqDate);
		head.setRespCode(respCode);
		head.setRespDate(respDate);
		head.setRespMsg(respMsg);
		head.setRespType(respType);
		head.setSmzfMsgId(smzfMsgId);
		return head;
	}
}
